home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-25 | 9.7 KB | 322 lines | [TEXT/CWIE] |
- //
- // This code sample answers the question: "How can I ask an
- // AppleShare server to authenticate an account/password pair
- // without mounting a volume?"
- //
- // It attempts to mount a volume with a name which is known to
- // be invalid. If VolumeMount claims the password didn't
- // work, then it didn't. If VolumeMount claims the volume
- // could not be mounted, then the password was valid.
- //
- // This is 100% predictable behavior and doesn't rely on any
- // hacks. However, it does fall into the category of
- // empirically discovered undocumented behavior. Specifically,
- // it counts on the AppleShare server authenticating before
- // searching for a volume of the specified name.
- //
- // You should exercise appropriate caution in making use of
- // this code. More detailed warnings below.
- //
- // Complaints and kudos to:
- //
- // Pete Gontier
- // Apple Macintosh Developer Technical Support
- // <gurgle@apple.com>
- //
-
- #define SystemSevenOrLater 1
- #define OLDROUTINELOCATIONS 0
- #define OLDROUTINENAMES 0
-
- #ifndef __ERRORS__
- # include <Errors.h>
- #endif
-
- #ifndef __FILES__
- # include <Files.h>
- #endif
-
- #ifndef __GESTALT__
- # include <Gestalt.h>
- #endif
-
- #ifndef __STRINGS__
- # include <Strings.h>
- #endif
-
- typedef unsigned char Str8 [9];
-
- #if GENERATINGPOWERPC
- #pragma options align=mac68k
- #endif
- struct MyAFPVolMountInfo
- {
- short length; /* length of this record */
- VolumeType media; /* type of media, always AppleShareMediaType */
- short flags; /* 0 = normal mount; set bit 0 to inhibit greeting messages */
- char nbpInterval; /* NBP interval parameter; 7 is a good choice */
- char nbpCount; /* NBP count parameter; 5 is a good choice */
- short uamType; /* User Authentication Method */
- short zoneNameOffset; /* offset from start of record to zoneName */
- short serverNameOffset; /* offset from start of record to serverName */
- short volNameOffset; /* offset from start of record to volName */
- short userNameOffset; /* offset from start of record to userName */
- short userPasswordOffset; /* offset from start of record to userPassword */
- short volPasswordOffset; /* offset from start of record to volPassword */
- Str31 zoneName; /* server's AppleTalk zone name */
- Str31 serverName; /* server name */
- Str27 volName; /* volume name */
- Str31 userName; /* user name (zero length Pascal string for guest) */
- Str8 userPassword; /* user password (zero length Pascal string if no user password) */
- char filler1; /* to word align volPassword */
- Str8 volPassword; /* volume password (zero length Pascal string if no volume password) */
- char filler2; /* to end record on word boundry */
- };
- #if GENERATINGPOWERPC
- #pragma options align=reset
- #endif
-
- typedef struct MyAFPVolMountInfo MyAFPVolMountInfo;
- typedef MyAFPVolMountInfo *MyAFPVolMountInfoPtr, **MyAFPVolMountInfoHandle;
-
- static pascal OSErr GetIndVRefNum (unsigned short ioVolIndex, short *vRefNum)
- {
- OSErr err = noErr;
- ParamBlockRec pbr;
-
- pbr.volumeParam.ioCompletion = nil;
- pbr.volumeParam.ioNamePtr = nil;
- pbr.volumeParam.ioVolIndex = ioVolIndex;
-
- if (!(err = PBGetVInfoSync (&pbr)))
- *vRefNum = pbr.volumeParam.ioVRefNum;
- else
- *vRefNum = 0;
-
- return err;
- }
-
- static pascal OSErr GetVolParms (short vRefNum, GetVolParmsInfoBuffer *gvpibp)
- {
- HParamBlockRec hpbr;
-
- hpbr.ioParam.ioCompletion = nil;
- hpbr.ioParam.ioNamePtr = nil;
- hpbr.ioParam.ioVRefNum = vRefNum;
- hpbr.ioParam.ioBuffer = (Ptr) gvpibp;
- hpbr.ioParam.ioReqCount = sizeof (*gvpibp);
-
- return PBHGetVolParmsSync (&hpbr);
- }
-
- static pascal OSErr GetVolMountInfoSize (short vRefNum, unsigned short *size)
- {
- ParamBlockRec pbr;
-
- pbr.ioParam.ioCompletion = nil;
- pbr.ioParam.ioVRefNum = vRefNum;
- pbr.ioParam.ioBuffer = (Ptr) size;
-
- return PBGetVolMountInfoSize (&pbr);
- }
-
- static pascal OSErr GetVolMountInfo (short vRefNum, VolMountInfoPtr vmip)
- {
- ParamBlockRec pbr;
-
- pbr.ioParam.ioCompletion = nil;
- pbr.ioParam.ioVRefNum = vRefNum;
- pbr.ioParam.ioBuffer = (Ptr) vmip;
-
- return PBGetVolMountInfo (&pbr);
- }
-
- static pascal OSErr VolumeMount (VolMountInfoPtr vmip)
- {
- ParamBlockRec pbr;
-
- pbr.ioParam.ioCompletion = nil;
- pbr.ioParam.ioBuffer = (Ptr) vmip;
-
- return PBVolumeMount (&pbr);
- }
-
- static pascal void BuildAFPVolMountInfo( short theFlags,
- char theNBPInterval,
- char theNBPCount,
- short theUAMType,
- Str31 theZoneName,
- Str31 theServerName,
- Str27 theVolName,
- Str31 theUserName,
- Str8 theUserPassWord,
- Str8 theVolPassWord,
- VolMountInfoPtr vmip)
- {
- MyAFPVolMountInfoPtr theAFPInfo = (MyAFPVolMountInfoPtr) vmip;
-
- /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */
- theAFPInfo->length = sizeof(MyAFPVolMountInfo);
- theAFPInfo->media = AppleShareMediaType;
- theAFPInfo->flags = theFlags;
- theAFPInfo->nbpInterval = theNBPInterval;
- theAFPInfo->nbpCount = theNBPCount;
- theAFPInfo->uamType = theUAMType;
- theAFPInfo->zoneNameOffset = (short)((long)theAFPInfo->zoneName - (long)theAFPInfo);
- theAFPInfo->serverNameOffset = (short)((long)theAFPInfo->serverName - (long)theAFPInfo);
- theAFPInfo->volNameOffset = (short)((long)theAFPInfo->volName - (long)theAFPInfo);
- theAFPInfo->userNameOffset = (short)((long)theAFPInfo->userName - (long)theAFPInfo);
- theAFPInfo->userPasswordOffset = (short)((long)theAFPInfo->userPassword - (long)theAFPInfo);
- theAFPInfo->volPasswordOffset = (short)((long)theAFPInfo->volPassword - (long)theAFPInfo);
-
- BlockMoveData(theZoneName, theAFPInfo->zoneName, theZoneName[0] + 1);
- BlockMoveData(theServerName, theAFPInfo->serverName, theServerName[0] + 1);
- BlockMoveData(theVolName, theAFPInfo->volName, theVolName[0] + 1);
- BlockMoveData(theUserName, theAFPInfo->userName, theUserName[0] + 1);
- BlockMoveData(theUserPassWord, theAFPInfo->userPassword, theUserPassWord[0] + 1);
- BlockMoveData(theVolPassWord, theAFPInfo->volPassword, theVolPassWord[0] + 1);
- }
-
- /*****************************************************************************/
-
- static pascal OSErr ExtractAFPVolMountInfo ( VolMountInfoPtr theVolMountInfo,
- short *theFlags,
- short *theUAMType,
- StringPtr theZoneName,
- StringPtr theServerName,
- StringPtr theVolName,
- StringPtr theUserName )
- {
- OSErr error;
- StringPtr tempPtr;
-
- /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */
- if ( theVolMountInfo->media == AppleShareMediaType )
- {
- MyAFPVolMountInfoPtr theAFPInfo = (MyAFPVolMountInfoPtr) theVolMountInfo;
-
- *theFlags = theAFPInfo->flags;
- *theUAMType = theAFPInfo->uamType;
-
- tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->zoneNameOffset);
- BlockMoveData(tempPtr, theZoneName, tempPtr[0] + 1);
-
- tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->serverNameOffset);
- BlockMoveData(tempPtr, theServerName, tempPtr[0] + 1);
-
- tempPtr = (StringPtr)(StringPtr)((long)theAFPInfo + theAFPInfo->volNameOffset);
- BlockMoveData(tempPtr, theVolName, tempPtr[0] + 1);
-
- tempPtr = (StringPtr)((long)theAFPInfo + theAFPInfo->userNameOffset);
- BlockMoveData(tempPtr, theUserName, tempPtr[0] + 1);
-
- error = noErr;
- }
- else
- {
- error = paramErr;
- }
-
- return ( error );
- }
-
- static pascal OSErr Authenticate (VolMountInfoPtr volMountInfoP)
- {
- OSErr err = noErr;
-
- short flags;
- short uamType;
- Str31 zoneName;
- Str31 serverName;
- Str27 volName;
- Str31 userName;
-
- if (!(err = ExtractAFPVolMountInfo
- (volMountInfoP,&flags,&uamType,zoneName,serverName,volName,userName)))
- {
- StringPtr volPassword = "\p",
- userPassword = "\pFoo",
- volName = "\pin:valid";
-
- BuildAFPVolMountInfo
- (flags,0,0,uamType,
- zoneName,serverName,volName,userName,userPassword,volPassword,
- volMountInfoP);
-
- err = VolumeMount (volMountInfoP);
-
- //
- // NOTE: unless you have a user password "Foo", at this point
- // 'err' will indicate a password rejection (-5203), EVEN
- // THOUGH the volume name is bogus as well. If the password is
- // valid, 'err' will contain no-such-volume (nsvErr, -35),
- // because there is in fact no such volume as 'volName', which
- // is of course because such a volume name is impossible.
- //
- // NOTE 2: This works ONLY because AppleShare servers with
- // which I tested authenticate a user/password pair BEFORE
- // attempting to find a volume by the given name. If
- // AppleShare ever changes, this code will break. In other
- // words, this code relies on an uncontrollable sequence of
- // events on another machine.
- //
- // NOTE 3: If this scheme breaks, VolumeMount will most probably
- // produce nsvErr even for valid account/password pairs.
- // IN NO CASE WILL ANY VOLUME BE MOUNTED.
- //
- }
-
- return err;
- }
-
- void main (void)
- {
- //
- // 'main' theory of operation: find an AppleShare volume,
- // get (most of) the info needed to mount it, unmount it,
- // attempt to mount it again as described above. NOTE:
- // 'Authenticate' *always* returns an error, so the loop's
- // exit conditions are fulfilled when the first AppleShare
- // volume is found and unmounted.
- //
-
- OSErr err;
- unsigned short ioVolIndex = 1;
-
- do
- {
- short vRefNum;
-
- err = GetIndVRefNum (ioVolIndex, &vRefNum);
- if (err == nsvErr)
- { err = noErr; break; }
- else if (!err)
- {
- GetVolParmsInfoBuffer gvpib;
- if (!(err = GetVolParms (vRefNum, &gvpib)))
- {
- unsigned short bufSize;
- err = GetVolMountInfoSize (vRefNum, &bufSize);
- if (err == -50) // vol does not support mount info
- err = noErr;
- else if (!err)
- {
- VolMountInfoPtr volMountInfoP = (VolMountInfoPtr) NewPtr (bufSize);
- if (!(err = MemError ( )))
- {
- if (!(err = GetVolMountInfo (vRefNum, volMountInfoP)))
- if (volMountInfoP->media == AppleShareMediaType)
- if (!(err = UnmountVol (nil, vRefNum)))
- err = Authenticate (volMountInfoP);
-
- DisposePtr ((Ptr) volMountInfoP);
- }
- }
- }
- }
-
- ++ioVolIndex;
- }
- while (!err);
- }
-